home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / timage.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  26KB  |  1,022 lines

  1. #include "timage.hpp"
  2.  
  3. void trans_image::make_color(int c)
  4. {
  5.   unsigned char *dp=data;
  6.   int y,x;
  7.   for (y=0;y<h;y++)
  8.   {
  9.     x=0;
  10.     while(x<w)
  11.     {
  12.       x+=*(dp++);
  13.       if (x<w)
  14.       {     
  15.     int run=*(dp++);
  16.     memset(dp,c,run);
  17.     x+=run;
  18.     dp+=run;
  19.       }
  20.     }
  21.   }
  22. }
  23.  
  24. image *trans_image::make_image()
  25. {
  26.   image *im=new image(w,h);
  27.   unsigned char *d=im->scan_line(0),*dp=data,*dline;
  28.   int y,x;
  29.   for (y=0;y<h;y++)
  30.   {
  31.     x=0;
  32.     dline=d;
  33.     memset(dline,0,w);
  34.     while(x<w)
  35.     {
  36.       int skip=*(dp++);
  37.       dline+=skip;
  38.       x+=skip;
  39.       if (x<w)
  40.       {     
  41.     int run=*(dp++);
  42.     memcpy(dline,dp,run);
  43.     x+=run;
  44.     dline+=run;
  45.     dp+=run;
  46.       }
  47.     }
  48.     d=im->next_line(y,d);
  49.   }
  50.   return im;
  51. }
  52.  
  53. trans_image::trans_image(image *im, char *name)
  54. {
  55.   int size=0,x,y;
  56.   unsigned char *sl,*datap,*marker; 
  57.   w=im->width();
  58.   h=im->height();
  59.   
  60.   // first we must find out how much data to allocate
  61.   for (y=0;y<im->height();y++)
  62.   {
  63.     sl=im->scan_line(y);
  64.     x=0;    
  65.     while (x<w)
  66.     {      
  67.       size++;     
  68.       while (x<w && *sl==0) { sl++; x++; }      
  69.                                  
  70.       if (x<w)
  71.       {
  72.         size++;  // byte for the size of the run    
  73.         while (x<w && (*sl)!=0)
  74.         {
  75.       size++;
  76.       x++;
  77.       sl++;      
  78.     }    
  79.       }
  80.     }        
  81.   }  
  82.  
  83. #ifdef MEM_CHECK
  84.   char st[80];
  85.   sprintf(st,"trans_image::data (%s)",name);
  86.   data=(unsigned char *)jmalloc(size,st);
  87. #else
  88.   data=(unsigned char *)jmalloc(size,"");
  89. #endif
  90.   int ww=im->width(),hh=im->height();
  91.   datap=data;
  92.   if (!datap)
  93.   { printf("size = %d %d (%d)\n",im->width(),im->height(),size);  }
  94.   CONDITION(datap,"malloc error for trans_image::data");
  95.   
  96.   for (y=0;y<hh;y++)  // now actually make the runs
  97.   {
  98.     sl=im->scan_line(y);
  99.     x=0;    
  100.     while (x<ww)
  101.     {      
  102.       *datap=0;  // start the skip at 0       
  103.       while (x<im->width() && (*sl)==0) 
  104.       { sl++; x++; (*datap)++; }      
  105.       datap++;      
  106.                                  
  107.       if (x<ww)
  108.       {
  109.         marker=datap;   // let marker be the run size
  110.     *marker=0;
  111.     datap++;    // skip over this spot        
  112.         while (x<im->width() && (*sl)!=0)
  113.         {    
  114.           (*marker)++;      
  115.       (*datap)=*sl;
  116.           datap++;      
  117.       x++;
  118.       sl++;            
  119.     }    
  120.       }
  121.     }        
  122.   }  
  123. }
  124.  
  125. void trans_image::put_scan_line(image *screen, int x, int y, int line)   // always transparent   
  126. {
  127.   short x1,y1,x2,y2;
  128.   screen->get_clip(x1,y1,x2,y2);
  129.   if (y+line<y1 || y+line>y2 || x>x2 || x+w-1<x1)            // clipped off completely?
  130.     return;
  131.  
  132.   unsigned char *datap=data;
  133.   int ix;  
  134.   while (line)            // skip scan line data until we get to the line of interest
  135.   {
  136.     for (ix=0;ix<w;)      
  137.     {      
  138.       ix+=*datap;        // skip blank space
  139.       datap++;
  140.       if (ix<w)          
  141.       {    
  142.     int run_length=*datap;     // skip run
  143.     ix+=run_length;
  144.     datap+=run_length+1;
  145.       }      
  146.     }
  147.     line--;    
  148.     y++;    
  149.   }
  150.   
  151.   
  152.   // now slam this list of runs to the screen
  153.   unsigned char *screen_line=screen->scan_line(y)+x;
  154.     
  155.   for (ix=0;ix<w;)             
  156.   {      
  157.     int skip=*datap;              // how much space to skip?
  158.     datap++;
  159.     screen_line+=skip;
  160.     ix+=skip;    
  161.     
  162.     if (ix<w)
  163.     {      
  164.       int run_length=*datap;
  165.       datap++;
  166.  
  167.       if (x+ix+run_length-1<x1)      // is this run clipped out totally?
  168.       {
  169.     datap+=run_length;
  170.     ix+=run_length;
  171.     screen_line+=run_length;
  172.       }
  173.       else
  174.       {     
  175.     if (x+ix<x1)                 // is the run clipped partially?
  176.     {    
  177.       int clip=(x1-(x+ix));    
  178.       datap+=clip;    
  179.       run_length-=clip;
  180.       screen_line+=clip;
  181.       ix+=clip;    
  182.     }
  183.  
  184.     if (x+ix>x2)                      // clipped totally on the right?  
  185.           return ;                        // we are done, return!
  186.     else if (x+ix+run_length-1>x2)    // partially clipped?
  187.     {
  188.       memcpy(screen_line,datap,(x+ix+run_length-1)-x2);   // slam what we can
  189.       return ;    // and return 'cause we are done with the line
  190.         } else
  191.         {
  192.       memcpy(screen_line,datap,run_length);    
  193.       screen_line+=run_length;
  194.         datap+=run_length;
  195.         ix+=run_length;            
  196.         }      
  197.       }    
  198.     }
  199.   }
  200.  
  201. }
  202.  
  203.  
  204. inline unsigned char *trans_image::clip_y(image *screen, int x1, int y1, int x2, int y2, 
  205.                    int x, int &y, int &ysteps)
  206. {
  207.   // check to see if it is total clipped out first
  208.   if (y+h<=y1 || y>y2 || x>x2 || x+w<=x1)
  209.     return NULL;
  210.  
  211.   register unsigned char *datap=data;  
  212.  
  213.  
  214.   ysteps=height();
  215.   
  216.   if (y<y1)  // check to see if the image gets clipped at the top
  217.   {
  218.  
  219.  
  220.     // because data is stored in runs, we need to skip over the top clipped portion
  221.     int skips=(y1-y);     // how many lines do we need to skip?    
  222.     ysteps-=skips;        // reduce h (number of lines to draw)
  223.     y=y1;                // start drawing here now
  224.     while (skips--)
  225.     {      
  226.       register int ix=0;
  227.       while (ix<w)
  228.       {    
  229.         ix+=(*datap);       // skip over empty space
  230.         datap++; 
  231.         if (ix<w)              
  232.         { ix+=*datap;         
  233.         datap+=(*datap)+1;   // skip over data
  234.         }    
  235.       }      
  236.     }
  237.   }
  238.   
  239.   if (y+ysteps>y2)  // check to see if it gets clipped at the bottom
  240.     ysteps-=(y+ysteps-y2-1);
  241.  
  242.   screen->add_dirty(max(x,x1),y,min(x+width()-1,x2),y+h-1);  
  243.   return datap;
  244.  
  245. void trans_image::put_image_filled(image *screen, int x, int y, 
  246.                    uchar fill_color)
  247. {
  248.  short x1,y1,x2,y2;
  249.   int slam_length,chop_length,ysteps;
  250.  
  251.   screen->get_clip(x1,y1,x2,y2);
  252.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  253.   if (!datap) return ;     // if clip_y says nothing to draw, return
  254.   
  255.   screen_line=screen->scan_line(y)+x;  
  256.   int sw=screen->width()-w;
  257.   x1-=x; x2-=x;
  258.   for (;ysteps>0;ysteps--)
  259.   {         
  260.     register int ix,slam_length;
  261.     for (ix=0;ix<w;)
  262.     {
  263.       int blank=(*datap);
  264.       memset(screen_line,fill_color,blank);
  265.       ix+=blank;       // skip over empty space
  266.       screen_line+=blank;
  267.       
  268.       datap++; 
  269.       if (ix<w)              
  270.       { 
  271.     slam_length=*datap;     // find the length of this run      
  272.     datap++;      
  273.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  274.     {
  275.       datap+=slam_length;
  276.       ix+=slam_length;
  277.       screen_line+=slam_length;
  278.     }
  279.     else
  280.     {                
  281.       if (ix<x1)                // the left side needs to be chopped ?
  282.       {                  
  283.         chop_length=(x1-ix); 
  284.         
  285.         if (chop_length>=slam_length)  // see if we chopped it all off
  286.         {                              // yes, we did
  287.           ix+=slam_length;             // advance everything to the end of run
  288.           screen_line+=slam_length;
  289.           datap+=slam_length;          
  290.           slam_length=0;           
  291.         } else
  292.         {         
  293.           slam_length-=chop_length;   // else advance everything to begining of slam  
  294.           ix+=chop_length;
  295.           screen_line+=chop_length;
  296.           datap+=chop_length;        
  297.         }        
  298.       }            
  299.  
  300.       if (slam_length)   // see if there is anything left to slam
  301.       {
  302.         if (ix+slam_length>x2) // see if right side needs to be chopped off
  303.           memcpy(screen_line,datap,x2-ix+1);
  304.         else
  305.           memcpy(screen_line,datap,slam_length);
  306.         datap+=slam_length;
  307.         ix+=slam_length;        
  308.         screen_line+=slam_length;
  309.       }                   
  310.     }
  311.       }      
  312.     }
  313.     screen_line+=sw;
  314.   }    
  315. }
  316.  
  317. void trans_image::put_image_offseted(image *screen, uchar *s_off)   // if screen x & y offset already calculated save a mul
  318. {
  319.   int ix,ysteps=height();
  320.   int screen_skip=screen->width()-w;
  321.   uchar skip,*datap=data;
  322.   for (;ysteps;ysteps--)
  323.   {
  324.     for (ix=0;ix<w;)
  325.     {
  326.       skip=*datap;       // skip leading blank space
  327.       datap++;
  328.       ix+=skip;
  329.       s_off+=skip;
  330.  
  331.       if (s_off<screen->scan_line(0))
  332.           printf("bad write");
  333.  
  334.  
  335.       if (ix<w)
  336.       {
  337.     skip=*datap;
  338.     datap++;
  339.     memcpy(s_off,datap,skip);
  340.     datap+=skip;
  341.     s_off+=skip;
  342.     ix+=skip;
  343.  
  344.     if (s_off>=screen->scan_line(screen->height()+1))
  345.             printf("bad write");
  346.       }
  347.     }
  348.     s_off+=screen_skip;
  349.   }
  350. }
  351.  
  352. void trans_image::put_image(image *screen, int x, int y) 
  353. {
  354.   short x1,y1,x2,y2;
  355.   int slam_length,chop_length,ysteps;
  356.  
  357.   screen->get_clip(x1,y1,x2,y2);
  358.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  359.   if (!datap) return ;     // if clip_y says nothing to draw, return
  360.   
  361.   screen_line=screen->scan_line(y)+x;  
  362.   int sw=screen->width();
  363.   x1-=x; x2-=x;
  364.   for (;ysteps>0;ysteps--)
  365.   {         
  366.     register int ix,slam_length;
  367.     for (ix=0;ix<w;)
  368.     {
  369.       ix+=(*datap);       // skip over empty space
  370.       datap++; 
  371.       if (ix<w)              
  372.       { 
  373.     slam_length=*datap;     // find the length of this run      
  374.     datap++;      
  375.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  376.     {
  377.       datap+=slam_length;
  378.       ix+=slam_length;        
  379.     }
  380.     else
  381.     {                
  382.       if (ix<x1)                // the left side needs to be chopped ?
  383.       {                  
  384.         chop_length=(x1-ix); 
  385.         
  386.         if (chop_length>=slam_length)  // see if we chopped it all off
  387.         {                              // yes, we did
  388.           ix+=slam_length;             // advance everything to the end of run
  389.           datap+=slam_length;          
  390.           slam_length=0;           
  391.         } else
  392.         {         
  393.           slam_length-=chop_length;   // else advance everything to begining of slam  
  394.           ix+=chop_length;
  395.           datap+=chop_length;        
  396.         }        
  397.       }            
  398.  
  399.       if (slam_length)   // see if there is anything left to slam
  400.       {
  401.         if (ix+slam_length>x2) // see if right side needs to be chopped off
  402.           memcpy(screen_line+ix,datap,x2-ix+1);
  403.         else
  404.           memcpy(screen_line+ix,datap,slam_length);
  405.         datap+=slam_length;
  406.         ix+=slam_length;        
  407.       }                   
  408.     }
  409.       }      
  410.     }
  411.     screen_line+=sw;
  412.   }    
  413. }
  414.  
  415. void trans_image::put_remaped(image *screen, int x, int y, unsigned char *remap) 
  416. {
  417.   short x1,y1,x2,y2;
  418.   int slam_length,chop_length,ysteps;
  419.  
  420.   screen->get_clip(x1,y1,x2,y2);
  421.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  422.   if (!datap) return ;     // if clip_y says nothing to draw, return
  423.   
  424.   screen_line=screen->scan_line(y)+x;  
  425.   int sw=screen->width();
  426.   x1-=x; x2-=x;
  427.   for (;ysteps>0;ysteps--)
  428.   {         
  429.     register int ix,slam_length;
  430.     for (ix=0;ix<w;)
  431.     {
  432.       ix+=(*datap);       // skip over empty space
  433.       datap++; 
  434.       if (ix<w)              
  435.       { 
  436.     slam_length=*datap;     // find the length of this run      
  437.     datap++;      
  438.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  439.     {
  440.       datap+=slam_length;
  441.       ix+=slam_length;        
  442.     }
  443.     else
  444.     {                
  445.       if (ix<x1)                // the left side needs to be chopped ?
  446.       {                  
  447.         chop_length=(x1-ix); 
  448.         
  449.         if (chop_length>=slam_length)  // see if we chopped it all off
  450.         {                              // yes, we did
  451.           ix+=slam_length;             // advance everything to the end of run
  452.           datap+=slam_length;          
  453.           slam_length=0;           
  454.         } else
  455.         {         
  456.           slam_length-=chop_length;   // else advance everything to begining of slam  
  457.           ix+=chop_length;
  458.           datap+=chop_length;        
  459.         }        
  460.       }            
  461.  
  462.  
  463.       if (slam_length)   // see if there is anything left to slam
  464.       {
  465.         register int counter;
  466.         if (ix+slam_length>x2) // see if right side needs to be chopped off        
  467.           counter=x2-ix+1;
  468.         else
  469.           counter=slam_length;
  470.  
  471.         register unsigned char *sl=screen_line+ix,*sl2=datap;
  472.         ix+=slam_length;        
  473.         datap+=slam_length;
  474.         while (counter)
  475.         {
  476.           counter--;
  477.           *(sl)=remap[*(sl2)];
  478.           sl++;
  479.           sl2++;
  480.         }
  481.       }                   
  482.     }
  483.       }      
  484.     }
  485.     screen_line+=sw;
  486.   }    
  487. }
  488.  
  489.  
  490.  
  491. void trans_image::put_double_remaped(image *screen, int x, int y, unsigned char *remap, unsigned char *remap2) 
  492. {
  493.   short x1,y1,x2,y2;
  494.   int slam_length,chop_length,ysteps;
  495.  
  496.   screen->get_clip(x1,y1,x2,y2);
  497.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  498.   if (!datap) return ;     // if clip_y says nothing to draw, return
  499.   
  500.   screen_line=screen->scan_line(y)+x;  
  501.   int sw=screen->width();
  502.   x1-=x; x2-=x;
  503.   for (;ysteps>0;ysteps--)
  504.   {         
  505.     register int ix,slam_length;
  506.     for (ix=0;ix<w;)
  507.     {
  508.       ix+=(*datap);       // skip over empty space
  509.       datap++; 
  510.       if (ix<w)              
  511.       { 
  512.     slam_length=*datap;     // find the length of this run      
  513.     datap++;      
  514.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  515.     {
  516.       datap+=slam_length;
  517.       ix+=slam_length;        
  518.     }
  519.     else
  520.     {                
  521.       if (ix<x1)                // the left side needs to be chopped ?
  522.       {                  
  523.         chop_length=(x1-ix); 
  524.         
  525.         if (chop_length>=slam_length)  // see if we chopped it all off
  526.         {                              // yes, we did
  527.           ix+=slam_length;             // advance everything to the end of run
  528.           datap+=slam_length;          
  529.           slam_length=0;           
  530.         } else
  531.         {         
  532.           slam_length-=chop_length;   // else advance everything to begining of slam  
  533.           ix+=chop_length;
  534.           datap+=chop_length;        
  535.         }        
  536.       }            
  537.  
  538.  
  539.       if (slam_length)   // see if there is anything left to slam
  540.       {
  541.         register int counter;
  542.         if (ix+slam_length>x2) // see if right side needs to be chopped off        
  543.           counter=x2-ix+1;
  544.         else
  545.           counter=slam_length;
  546.  
  547.         register unsigned char *sl=screen_line+ix,*sl2=datap;
  548.         ix+=slam_length;        
  549.         datap+=slam_length;
  550.         while (counter)
  551.         {
  552.           counter--;
  553.           *(sl)=remap2[remap[*(sl2)]];
  554.           sl++;
  555.           sl2++;
  556.         }
  557.       }                   
  558.     }
  559.       }      
  560.     }
  561.     screen_line+=sw;
  562.   }    
  563. }
  564.  
  565.  
  566.  
  567. void trans_image::put_fade(image *screen, int x, int y,
  568.                int frame_on, int total_frames, 
  569.                color_filter *f, palette *pal) 
  570. {
  571.   short x1,y1,x2,y2;
  572.   int ix,slam_length,chop_length,ysteps;
  573.  
  574.   screen->get_clip(x1,y1,x2,y2);
  575.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  576.                 *screen_line;
  577.   if (!datap) return ;
  578.  
  579.   unsigned char *screen_run,*paddr=(unsigned char *)pal->addr(),
  580.                 *caddr1,*caddr2,r_dest,g_dest,b_dest;
  581.  
  582.   long fixmul=(frame_on<<16)/total_frames;
  583.   for (;ysteps>0;ysteps--,y++)
  584.   {         
  585.     screen_line=screen->scan_line(y);
  586.       
  587.     for (ix=0;ix<w;)
  588.     {
  589.       ix+=(*datap);       // skip over empty space
  590.       datap++; 
  591.       if (ix<w)              
  592.       { 
  593.     slam_length=*datap;     // find the length of this run      
  594.     datap++;      
  595.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  596.     {
  597.       datap+=slam_length;
  598.       ix+=slam_length;        
  599.     }
  600.     else
  601.     {                
  602.       if (x+ix<x1)                // the left side needs to be chopped ?
  603.       {                  
  604.         chop_length=(x1-x-ix); 
  605.         
  606.         if (chop_length>=slam_length)  // see if we chopped it all off
  607.         {                              // yes, we did
  608.           ix+=slam_length;             // advance everything to the end of run
  609.           datap+=slam_length;          
  610.           slam_length=0;           
  611.         } else
  612.         {         
  613.           slam_length-=chop_length;   // else advance everything to begining of slam  
  614.           ix+=chop_length;
  615.           datap+=chop_length;        
  616.         }        
  617.       }            
  618.  
  619.       if (slam_length)   // see if there is anything left to slam
  620.       {
  621.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  622.           chop_length=x2-x-ix;
  623.         else chop_length=slam_length;
  624.         screen_run=screen_line+x+ix;
  625.               
  626.         slam_length-=chop_length;
  627.         ix+=chop_length;
  628.           
  629.         while (chop_length--)
  630.         {
  631.           caddr1=paddr+(int)(*screen_run)*3;
  632.           caddr2=paddr+(int)(*datap)*3;
  633.           
  634.           r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  635.           caddr1++; caddr2++;
  636.  
  637.           g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  638.           caddr1++; caddr2++;
  639.  
  640.           b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  641.           *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
  642.  
  643.           screen_run++;
  644.           datap++;        
  645.         }
  646.         datap+=slam_length;
  647.         ix+=slam_length;        
  648.       }                   
  649.     }
  650.       }      
  651.     }      
  652.   }    
  653. }
  654.  
  655.  
  656.  
  657.  
  658. void trans_image::put_fade_tint(image *screen, int x, int y,
  659.                 int frame_on, int total_frames, 
  660.                 uchar *tint,
  661.                 color_filter *f, palette *pal) 
  662. {
  663.   short x1,y1,x2,y2;
  664.   int ix,slam_length,chop_length,ysteps;
  665.  
  666.   screen->get_clip(x1,y1,x2,y2);
  667.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  668.                 *screen_line;
  669.   if (!datap) return ;
  670.  
  671.   unsigned char *screen_run,*paddr=(unsigned char *)pal->addr(),
  672.                 *caddr1,*caddr2,r_dest,g_dest,b_dest;
  673.  
  674.   long fixmul=(frame_on<<16)/total_frames;
  675.   for (;ysteps>0;ysteps--,y++)
  676.   {         
  677.     screen_line=screen->scan_line(y);
  678.       
  679.     for (ix=0;ix<w;)
  680.     {
  681.       ix+=(*datap);       // skip over empty space
  682.       datap++; 
  683.       if (ix<w)              
  684.       { 
  685.     slam_length=*datap;     // find the length of this run      
  686.     datap++;      
  687.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  688.     {
  689.       datap+=slam_length;
  690.       ix+=slam_length;        
  691.     }
  692.     else
  693.     {                
  694.       if (x+ix<x1)                // the left side needs to be chopped ?
  695.       {                  
  696.         chop_length=(x1-x-ix); 
  697.         
  698.         if (chop_length>=slam_length)  // see if we chopped it all off
  699.         {                              // yes, we did
  700.           ix+=slam_length;             // advance everything to the end of run
  701.           datap+=slam_length;          
  702.           slam_length=0;           
  703.         } else
  704.         {         
  705.           slam_length-=chop_length;   // else advance everything to begining of slam  
  706.           ix+=chop_length;
  707.           datap+=chop_length;        
  708.         }        
  709.       }            
  710.  
  711.       if (slam_length)   // see if there is anything left to slam
  712.       {
  713.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  714.           chop_length=x2-x-ix;
  715.         else chop_length=slam_length;
  716.         screen_run=screen_line+x+ix;
  717.               
  718.         slam_length-=chop_length;
  719.         ix+=chop_length;
  720.           
  721.         while (chop_length--)
  722.         {
  723.           caddr1=paddr+(int)(*screen_run)*3;
  724.           caddr2=paddr+(int)(tint[*datap])*3;
  725.           
  726.           r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  727.           caddr1++; caddr2++;
  728.  
  729.           g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  730.           caddr1++; caddr2++;
  731.  
  732.           b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  733.           *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
  734.  
  735.           screen_run++;
  736.           datap++;        
  737.         }
  738.         datap+=slam_length;
  739.         ix+=slam_length;        
  740.       }                   
  741.     }
  742.       }      
  743.     }      
  744.   }    
  745. }
  746.  
  747.  
  748.  
  749.  
  750.  
  751.  
  752. void trans_image::put_color(image *screen, int x, int y, int color) 
  753. {
  754.   short x1,y1,x2,y2;
  755.   int ix,slam_length,chop_length,ysteps;
  756.   
  757.   screen->get_clip(x1,y1,x2,y2);
  758.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  759.                 *screen_line;
  760.   if (!datap) return ;
  761.   
  762.   
  763.   for (;ysteps>0;ysteps--,y++)
  764.   {         
  765.     screen_line=screen->scan_line(y);
  766.       
  767.     for (ix=0;ix<w;)
  768.     {
  769.       ix+=(*datap);       // skip over empty space
  770.       datap++; 
  771.       if (ix<w)              
  772.       { 
  773.     slam_length=*datap;     // find the length of this run      
  774.     datap++;      
  775.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  776.     {
  777.       datap+=slam_length;
  778.       ix+=slam_length;        
  779.     }
  780.     else
  781.     {                
  782.       if (x+ix<x1)                // the left side needs to be chopped ?
  783.       {                  
  784.         chop_length=(x1-x-ix); 
  785.         
  786.         if (chop_length>=slam_length)  // see if we chopped it all off
  787.         {                              // yes, we did
  788.           ix+=slam_length;             // advance everything to the end of run
  789.           datap+=slam_length;          
  790.           slam_length=0;           
  791.         } else
  792.         {         
  793.           slam_length-=chop_length;   // else advance everything to begining of slam  
  794.           ix+=chop_length;
  795.           datap+=chop_length;        
  796.         }        
  797.       }            
  798.  
  799.       if (slam_length)   // see if there is anything left to slam
  800.       {
  801.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  802.           memset(screen_line+x+ix,color,x2-x-ix+1);
  803.         else
  804.           memset(screen_line+x+ix,color,slam_length);
  805.         datap+=slam_length;
  806.         ix+=slam_length;        
  807.       }    
  808.     }
  809.       }      
  810.     }      
  811.   }    
  812. }
  813.  
  814.  
  815. // ASSUMES that the blend image completly covers this image
  816. void trans_image::put_blend16(image *screen, image *blend, int x, int y, 
  817.                   int blendx, int blendy, int blend_amount, color_filter *f, palette *pal)
  818.  
  819. {
  820.   short x1,y1,x2,y2;
  821.   int ix,slam_length,chop_length,ysteps,rx1,rx2;
  822.   unsigned char *paddr=(unsigned char *)pal->addr();  
  823.   
  824.   screen->get_clip(x1,y1,x2,y2);
  825.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  826.                 *blend_line,*screen_line;
  827.   if (!datap) return ;
  828.   CONDITION(y>=blendy && y+ysteps<blendy+blend->height()+1,"Blend doesn't fit on trans_image");
  829.   
  830.   blend_amount=16-blend_amount;
  831.   
  832.   for (;ysteps>0;ysteps--,y++)
  833.   {         
  834.     screen_line=screen->scan_line(y);
  835.     blend_line=blend->scan_line(y-blendy);
  836.     
  837.       
  838.     for (ix=0;ix<w;)
  839.     {
  840.       ix+=(*datap);       // skip over empty space
  841.       datap++; 
  842.       if (ix<w)              
  843.       { 
  844.     slam_length=*datap;     // find the length of this run      
  845.     datap++;      
  846.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  847.     {
  848.       datap+=slam_length;
  849.       ix+=slam_length;        
  850.     }
  851.     else
  852.     {                
  853.       if (x+ix<x1)                // the left side needs to be chopped ?
  854.       {                  
  855.         chop_length=(x1-x-ix); 
  856.         
  857.         if (chop_length>=slam_length)  // see if we chopped it all off
  858.         {                              // yes, we did
  859.           ix+=slam_length;             // advance everything to the end of run
  860.           datap+=slam_length;          
  861.           slam_length=0;           
  862.         } else
  863.         {         
  864.           slam_length-=chop_length;   // else advance everything to begining of slam  
  865.           ix+=chop_length;
  866.           datap+=chop_length;        
  867.         }        
  868.       }            
  869.  
  870.       if (slam_length)   // see if there is anything left to slam
  871.       {
  872.  
  873.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  874.           chop_length=x2-x-ix;
  875.         else chop_length=slam_length;
  876.  
  877.         unsigned char *screen_run=screen_line+x+ix,
  878.                       *blend_run=blend_line+x+ix-blendx,
  879.                       *caddr1,*caddr2,r_dest,g_dest,b_dest;      
  880.               
  881.         slam_length-=chop_length;
  882.         ix+=chop_length;    
  883.  
  884.  
  885.         while (chop_length--)
  886.         {
  887.           caddr1=paddr+(int)(*blend_run)*3;
  888.           caddr2=paddr+(int)(*datap)*3;
  889.           
  890.           r_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
  891.           caddr1++; caddr2++;
  892.  
  893.           g_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
  894.           caddr1++; caddr2++;
  895.  
  896.           b_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
  897.  
  898.           *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
  899.  
  900.           
  901.           screen_run++;
  902.           blend_run++;
  903.           datap++;        
  904.         }
  905.         datap+=slam_length;
  906.         ix+=slam_length;        
  907.       }                 
  908.  
  909.     }
  910.       }      
  911.     }      
  912.   }    
  913.  
  914.  
  915. }
  916.  
  917. void trans_image::put_predator(image *screen, int x, int y) 
  918. {
  919.   short x1,y1,x2,y2;
  920.   int slam_length,chop_length,ysteps;
  921.  
  922.   screen->get_clip(x1,y1,x2,y2);
  923.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  924.   if (!datap) return ;     // if clip_y says nothing to draw, return
  925.  
  926.   // see if the last scanline is clipped off
  927.   if (y+ysteps==y2) ysteps-=2;
  928.   else if (y+ysteps==y2-1) ysteps--;
  929. /*  {
  930.     for (int x=0;x<w;)
  931.     {
  932.       int skip=*datap; datap++;
  933.       x+=skip;
  934.       if (x<w)
  935.       {
  936.     int run_size=*datap;
  937.     datap+=run_size+1;
  938.     x+=run_size;
  939.       }
  940.     }
  941.     if (y==y2) 
  942.       return;
  943.     else
  944.       y++;    
  945.   }*/
  946.   
  947.   screen_line=screen->scan_line(y)+x;  
  948.   int sw=screen->width();
  949.   x1-=x; x2-=x;
  950.   for (;ysteps>0;ysteps--)
  951.   {         
  952.     register int ix,slam_length;
  953.     for (ix=0;ix<w;)
  954.     {
  955.       ix+=(*datap);       // skip over empty space
  956.       datap++; 
  957.       if (ix<w)              
  958.       { 
  959.     slam_length=*datap;     // find the length of this run      
  960.     datap++;      
  961.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  962.     {
  963.       datap+=slam_length;
  964.       ix+=slam_length;        
  965.     }
  966.     else
  967.     {                
  968.       if (ix<x1)                // the left side needs to be chopped ?
  969.       {                  
  970.         chop_length=(x1-ix); 
  971.         
  972.         if (chop_length>=slam_length)  // see if we chopped it all off
  973.         {                              // yes, we did
  974.           ix+=slam_length;             // advance everything to the end of run
  975.           datap+=slam_length;          
  976.           slam_length=0;           
  977.         } else
  978.         {         
  979.           slam_length-=chop_length;   // else advance everything to begining of slam  
  980.           ix+=chop_length;
  981.           datap+=chop_length;        
  982.         }        
  983.       }            
  984.  
  985.       if (slam_length)   // see if there is anything left to slam
  986.       {
  987.         if (ix+slam_length>x2) // see if right side needs to be chopped off
  988.           memcpy(screen_line+ix,screen_line+sw+sw+ix,x2-ix+1);
  989.         else
  990.           memcpy(screen_line+ix,screen_line+sw+sw+ix,slam_length);
  991.         datap+=slam_length;
  992.         ix+=slam_length;        
  993.       }                   
  994.     }
  995.       }      
  996.     }
  997.     screen_line+=sw;
  998.   }    
  999. }
  1000.  
  1001. int trans_image::size()
  1002. {
  1003.   uchar *d=data;
  1004.   int t=0;
  1005.   for (int y=0;y<h;y++)
  1006.   {
  1007.     int x=0;
  1008.     while (x<w)
  1009.     {
  1010.       x+=*d; d++; t++;
  1011.       if (x<w)
  1012.       {
  1013.     int s=*d; d++; t+=s+1;
  1014.     d+=s;
  1015.     x+=s;
  1016.       }      
  1017.     }
  1018.   }
  1019.   return t+4+4;
  1020. }
  1021.